﻿#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/rsa.h>
#include <openssl/pem.h>

#define RSA_KSRV_PRIVATE_KEY_NAME "ksrvpriv.key"
#define RSA_PRIVATE_KEY_NAME "kusrpriv.key"
#define RSA_PUBLIC_KEY_NAME "kusrpub.key"
#define TOKEN_FILE_NAME  "token.dat"

#define err(fmt, ...) do {err(fmt"\n", ##__VA_ARGS__); } while(0)

int generate_token(BIO *bio_pub)
{
	BIO *token;
	RSA *ksrvprivkey;
	FILE *fp;
	unsigned char *buffer, *p, *buffer_encrypt, *buffer_decrypt;
	int len = BIO_number_written(bio_pub);
	int flen;
	int total_len;
	int icount;	//passed to rsa encryt 
	int ret;

	token = BIO_new_file(TOKEN_FILE_NAME, "wb");

	if (!(buffer = malloc(len << 1))) {
		err("malloc failed");
		return 1;
	}
	p = buffer;
	
	*p++ = 0xE0;
	*p++ = len & 0xFF;
	*p++ = (len >> 8) & 0xFF;
	
	BIO_read(bio_pub, p, len);
	p += len;
	
	// append other infomation
	len = 5;
	*p++ = 0xE1;
	*p++ = 5;
	*p++ = 0;
	memcpy(p, "1234", len);
	
	p += len;
	
	total_len = p - buffer;

	
	fp = fopen(RSA_KSRV_PRIVATE_KEY_NAME, "rb");
	if (!(ksrvprivkey = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL))) {
		err("open server private key failed\n");
		return 1;
	}
    ret = RSA_check_key(ksrvprivkey);

    if(ret != 1) {
        printf("key error!\n");
        return 1;
    }

	// encrypt token by using server private key
	flen = RSA_size(ksrvprivkey);
	icount = flen - 11;	// input block size
	buffer_encrypt = malloc(flen);	// output block size
	for (p = buffer; total_len > 0; total_len -= icount, p += icount) {
		if (total_len < icount)
			icount = total_len;
		printf("icount %d\n", icount);
		if (!icount)
			break;
		ret = RSA_private_encrypt(icount, p, buffer_encrypt, ksrvprivkey, RSA_PKCS1_PADDING);
		if (ret <= 0) {
			err("encrypt failed");
			return 1;
		}
		BIO_write(token, buffer_encrypt, ret);
	}
	
	RSA_free(ksrvprivkey);
	BIO_free(token);
	free(buffer);
	free(buffer_encrypt);

	return 0;
}

int main(int argc, char *argv[])
{
    RSA *pRsa;
    int bits=1024, iret;
    unsigned long e = RSA_3;
    FILE *pfprivatekey, *pfpublickey;
	BIO *bio_pub;

    if(!(pfpublickey = fopen(RSA_PUBLIC_KEY_NAME, "wb"))) {
        err("open file [ %s ] error!", RSA_PUBLIC_KEY_NAME);
        exit(0);
    }

    if(!(pfprivatekey = fopen(RSA_PRIVATE_KEY_NAME, "wb"))) {
        err("open file [ %s ] error!", RSA_PRIVATE_KEY_NAME);
        exit(0);
    }

    pRsa = RSA_generate_key(bits, e, NULL, NULL);

    iret = RSA_check_key(pRsa);
    if(iret != 1) {
        err("key error!");
        return 1;
    }

	/* write pem public key and private key to file */
    PEM_write_RSAPublicKey(pfpublickey, pRsa);
    PEM_write_RSAPrivateKey(pfprivatekey, pRsa, NULL, NULL, bits, NULL, NULL);
	
	bio_pub = BIO_new(BIO_s_mem());
	iret = PEM_write_bio_RSAPublicKey(bio_pub, pRsa);
	generate_token(bio_pub);
	
	BIO_free(bio_pub);
	
    RSA_free(pRsa);
    fclose(pfpublickey);
    fclose(pfprivatekey);

    return 0;
}